package org.beetl.core.io;

import java.io.IOException;

import org.beetl.core.ByteWriter;

public class LongIOWriter
{
	public static void writeLong(ByteWriter bw, Long i) throws IOException
	{
		if (i == Long.MIN_VALUE)
		{
			bw.writeString("-9223372036854775808");
			return;
		}
		int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
		char[] buf = bw.getLocalBuffer().getCharBuffer();
		getChars(i, size, buf);
		bw.writeNumberChars(buf, size);

	}

	static void getChars(long i, int index, char[] buf)
	{
		long q;
		int r;
		int charPos = index;
		char sign = 0;

		if (i < 0)
		{
			sign = '-';
			i = -i;
		}

		// Get 2 digits/iteration using longs until quotient fits into an int
		while (i > Integer.MAX_VALUE)
		{
			q = i / 100;
			// really: r = i - (q * 100);
			r = (int) (i - ((q << 6) + (q << 5) + (q << 2)));
			i = q;
			buf[--charPos] = IntIOWriter.DigitOnes[r];
			buf[--charPos] = IntIOWriter.DigitTens[r];
		}

		// Get 2 digits/iteration using ints
		int q2;
		int i2 = (int) i;
		while (i2 >= 65536)
		{
			q2 = i2 / 100;
			// really: r = i2 - (q * 100);
			r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
			i2 = q2;
			buf[--charPos] = IntIOWriter.DigitOnes[r];
			buf[--charPos] = IntIOWriter.DigitTens[r];
		}

		// Fall thru to fast mode for smaller numbers
		// assert(i2 <= 65536, i2);
		for (;;)
		{
			q2 = (i2 * 52429) >>> (16 + 3);
			r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
			buf[--charPos] = IntIOWriter.digits[r];
			i2 = q2;
			if (i2 == 0)
				break;
		}
		if (sign != 0)
		{
			buf[--charPos] = sign;
		}
	}

	// Requires positive x
	static int stringSize(long x)
	{
		long p = 10;
		for (int i = 1; i < 19; i++)
		{
			if (x < p)
				return i;
			p = 10 * p;
		}
		return 19;
	}

}
